var http = require('http');
var qs = require('querystring');
var dgram = require('dgram');
var util = require('util');
var timers = require('timers');
require('buffer');

/**
 * Mockup of the HTTP and UDP interfaces of the PIC32 device controller.
 * 
 * @name TestDevice
 * @class TestDevice
 * @author jmanero
 * 
 * @requires http
 * @requires querystring
 * @requires dgram
 * @requires buffer
 * @requires util
 * @requires timers
 * 
 */

/**
 * Describes the port configuration of simulatied devcice
 * 
 * @memberOf TestDevice
 * 
 */
var device = {
	ports : {
		io0 : {
			direction : 'Input',
			type : 'Boolean',
			value : false
		},
		io1 : {
			direction : 'Output',
			type : 'Boolean',
			value : false
		},
		io2 : {
			direction : 'Output',
			type : 'Boolean',
			value : false
		},
		adc0 : {
			direction : 'Input',
			type : 'Number',
			value : 0
		}
	},
	name : "TASKSERVER",
	mac : "00-0f-1f-e1-a9-9e"
};

device.name += '               ';
device.name = device.name.slice(0, 15);

/**
 * 'Blink' boolean inputs on or off every second
 * 
 * @event
 * @name blink
 * @memberOf TestDevice
 * 
 */
var blink = timers.setInterval(function() {
	for ( var p in device.ports) {
		if (device.ports[p].direction == 'Input'
				&& device.ports[p].type == 'Boolean') {
			device.ports[p].value = !(device.ports[p].value);
		}
	}
}, 1000);

/**
 * Generate a sine wave with 0.25 second resolution at each numeric input
 * 
 * @event
 * @name sine
 * @memberOf TestDevice
 * 
 */
var sine = timers.setInterval(function() {
	var date = new Date();
	for ( var p in device.ports) {
		if (device.ports[p].direction == 'Input'
				&& device.ports[p].type == 'Number') {
			device.ports[p].value = Math.sin(date.getTime());
		}
	}
}, 250);

/**
 * Listen for HTTP requests. If POST, parse request body and try to match fields
 * to Output ports to update
 * 
 * @memberOf TestDevice
 * 
 */
var httpServer = http.createServer(function(request, response) {
	if (request.method == 'post') {
		var data = '', body;
		request.on('data', function(chunk) {
			data += chunk;
		});

		request.on('end', function() {
			body = qs.parse(data);
			for ( var b in body) {
				if (device.ports[b].type == 'Output') {
					device.ports[b].value = body[b];
				}
			}
		});
	}

	response.writeHead(200, {
		'Content-Type' : 'x-application/json'
	});

	response.write('{');
	var first = true;
	for ( var p in device.ports) {
		if (!first)
			response.write(',');
		response.write('"' + p + '" : "' + device.ports[p].value + '"');
		first = false;
	}
	response.write('}');
	response.end();

});

httpServer.listen(9001, '172.16.1.254');

/**
 * UDP server to respond to locator requests
 * 
 * @memberOf TestDevice
 */
var udpServer = dgram.createSocket('udp4');

/**
 * Locator response message
 * 
 * @type Buffer
 * @memberOf TestDevices
 */
var message = Buffer(device.name + "\r\n" + device.mac + "\r\n");

/**
 * Send the locator response
 * 
 * @event
 * @name message
 * @memberOf TestDevice#udpServer
 */
udpServer.on('message', function(buffer, rinfo) {
	udpServer.send(message, 0, message.length, rinfo.port, rinfo.address);
});

udpServer.bind(30303);
